unit KRK.Lib.Rtl.Common.VariantUtils;

{$WEAKPACKAGEUNIT ON}

interface

uses Classes, SysUtils;

function OleVariantByteArrayToMemoryStream(const aOleVariant: OleVariant): TMemoryStream;
function OleVariantByteArrayFromMemoryStream(const aMemoryStream: TMemoryStream): OleVariant;
function OleVariantByteArrayToString(const aOleVariant: OleVariant): String;
function OleVariantByteArrayFromString(const aString: String): OleVariant;
procedure OleVariantByteArrayToFile(const aOleVariant: OleVariant; const aFileName: TFileName);
function OleVariantByteArrayFromFile(const aFileName: TFileName): OleVariant;
procedure OleVariantByteArrayUCLCompress(var aOleVariant: OleVariant);
procedure OleVariantByteArrayUCLDecompress(var aOleVariant: OleVariant);
function OleVariantByteArraySize(const aOleVariant: OleVariant): Cardinal;

implementation

uses Variants, KRK.Lib.DIUcl.Streams, KRK.Lib.rtl.common.fileutils;

function OleVariantByteArraySize(const aOleVariant: OleVariant): Cardinal;
begin
  Result := Succ(VarArrayHighBound(aOleVariant, 1) - VarArrayLowBound(aOleVariant, 1));
end;

function OleVariantByteArrayToMemoryStream(const aOleVariant: OleVariant): TMemoryStream;
var
  Data: Pointer;
  Size: integer;
begin
  Result := TMemoryStream.Create;
  try
    Size := OleVariantByteArraySize(aOleVariant);

    Data := VarArrayLock(aOleVariant);
    try
      Result.WriteBuffer(Data^, Size);
    finally
      Result.Position := 0;
      VarArrayUnlock(aOleVariant);
    end;
  except
    FreeAndNil(Result);
  end;
end;

function OleVariantByteArrayFromMemoryStream(const aMemoryStream: TMemoryStream): OleVariant;
var
  Data: Pointer;
  OldPosition: Int64;
begin
  Result := Unassigned;

  Result := VarArrayCreate([0, Pred(aMemoryStream.Size)], varByte);
  Data := VarArrayLock(Result);

  OldPosition := aMemoryStream.Position;
  try
    aMemoryStream.Position := 0;
    aMemoryStream.ReadBuffer(Data^,aMemoryStream.Size);
  finally
    aMemoryStream.Position := OldPosition;
    VarArrayUnlock(Result);
  end;
end;

function VariantArrayToString(const V: OleVariant): string;
var
  P: Pointer;
  Size: Integer;
begin
  Result := '';
  if VarIsArray(V) and (VarType(V) and varTypeMask = varByte) then
  begin
    Size := VarArrayHighBound(V, 1) - VarArrayLowBound(V, 1) + 1;
    if Size > 0 then
    begin
      SetLength(Result, Size);
      P := VarArrayLock(V);
      try
        Move(P^, Result[1], Size);
      finally
        VarArrayUnlock(V);
      end;
    end;
  end;
end;

function StringToVariantArray(const S: string): OleVariant;
var
  P: Pointer;
begin
  Result := NULL;
  if Length(S) > 0 then
  begin
    Result := VarArrayCreate([0, Length(S) - 1], varByte);
    P := VarArrayLock(Result);
    try
      Move(S[1], P^, Length(S));
    finally
      VarArrayUnlock(Result);
    end;
  end;
end;

function OleVariantByteArrayToString(const aOleVariant: OleVariant): String;
begin
  Result := String(VariantArrayToString(aOleVariant));
end;

function OleVariantByteArrayFromString(const aString: String): OleVariant;
begin
  Result := StringToVariantArray(String(RawByteString(aString)));
end;

procedure OleVariantByteArrayUCLCompress(var aOleVariant: OleVariant);
var
  MemoryStream: TMemoryStream;
begin
  if VarIsNull(aOleVariant) then
    Exit;

  MemoryStream := TMemoryStream.Create;
  try
    UclCompressStream(OleVariantByteArrayToMemoryStream(aOleVariant),MemoryStream);

    aOleVariant := OleVariantByteArrayFromMemoryStream(MemoryStream);
  finally
    FreeAndNil(MemoryStream);
  end;
end;

procedure OleVariantByteArrayUCLDecompress(var aOleVariant: OleVariant);
var
  MemoryStream: TMemoryStream;
begin
  if VarIsNull(aOleVariant) then
    Exit;

  MemoryStream := TMemoryStream.Create;
  try
    UclDeCompressStream(OleVariantByteArrayToMemoryStream(aOleVariant),MemoryStream);

    aOleVariant := OleVariantByteArrayFromMemoryStream(MemoryStream);
  finally
    FreeAndNil(MemoryStream);
  end;
end;

procedure OleVariantByteArrayToFile(const aOleVariant: OleVariant; const aFileName: TFileName);
var
  MemoryStream: TMemoryStream;
begin
  with TFileStream.Create(aFileName,fmCreate,fmShareDenyWrite) do
    try
      MemoryStream := OleVariantByteArrayToMemoryStream(aOleVariant);
      CopyFrom(MemoryStream,MemoryStream.Size);
    finally
      Free;
    end;
end;

function OleVariantByteArrayFromFile(const aFileName: TFileName): OleVariant;
var
  FileStream: TFileStream;
  MemoryStream: TMemoryStream;
begin
  Result := Unassigned;

  FileStream := TFileStream.Create(aFileName,fmOpenRead,fmShareDenyWrite);
  MemoryStream := TMemoryStream.Create;

  try
    MemoryStream.CopyFrom(FileStream,FileStream.Size);
    Result := OleVariantByteArrayFromMemoryStream(MemoryStream);
  finally
    MemoryStream.Free;
    FileStream.Free;
  end;
end;

end.
